package com.example.tutorial.java.concurrent.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 实现多线程的方式及适用场景
 * <p>
 * 实现多线程任务方式一，实现Callable接口，覆写call方法
 * 适用于以下场景：
 * 1.线程任务有返回值
 * 2.无法直接implements Runnable
 * <p>
 * 实现多线程任务方式二，实现Runnable接口，覆写run方法
 * 适用于以下场景：
 * 1.线程任务无返回值
 * 2.无法直接extends Thread
 * <p>
 * 实现多线程任务方式三，继承Thread类，覆写run方法
 * 本质上仍是实现Runnable接口
 * 适用于以下场景：
 * 1.线程任务无返回值
 * 2.无法直接implements Runnable
 *
 * @author chenpenghui
 * @date 2021-3-10
 */
public class ThreadReturnValueTest {
    public static void main(String[] args) throws Exception {

//        myRunnable();
//        myCallable();

        timeoutException();
    }

    private static void timeoutException() throws InterruptedException {

        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        Future<Object> submit = singleThreadExecutor.submit(new MyCallable(1));
        Object obj;
        try {
            // 等待时间为2s，超时直接报TimeoutException
            obj = submit.get(2, TimeUnit.SECONDS);
        } catch (ExecutionException e) {
            obj = "ExecutionException";
        } catch (TimeoutException e) {
            obj = "TimeoutException";
            // 任务超时后已无再执行的必要，直接取消
            submit.cancel(true);
        }
        System.out.println(obj);

    }

    private static void myRunnable() {
        MyRunnable myRunnable = new MyRunnable();

        Thread t1 = new Thread(myRunnable);
        Thread t2 = new Thread(myRunnable);

        t1.start();
        t2.start();
    }

    private static void myCallable() throws InterruptedException, java.util.concurrent.ExecutionException {
        // 创建线程池
        int taskSize = 5;
        ExecutorService pool = Executors.newFixedThreadPool(taskSize);

        // 创建有返回值的任务
        List<Future> list = new ArrayList<>();
        for (int i = 0; i < taskSize; i++) {
            MyCallable callable = new MyCallable(i);
            // 执行任务并获取Future对象
            Future<Object> future = pool.submit(callable);
            list.add(future);
        }
        // 关闭线程池
        pool.shutdown();

        for (Future f : list) {
            System.out.println("---" + f.get().toString());
        }
    }

    static class MyCallable implements Callable<Object> {

        private Integer taskNum;

        public MyCallable(Integer taskNum) {
            this.taskNum = taskNum;
        }

        @Override
        public Object call() throws Exception {
            long start = System.currentTimeMillis();
            Thread.sleep(3000);
            long end = System.currentTimeMillis();
            return "任务" + taskNum + "返回结果，耗时" + (end - start) + "ms";
        }
    }

    static class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("current thread: " + Thread.currentThread().getName());
        }
    }

    static class MyThread extends Thread {

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }

}
